#include <crt_util.h>

int is_utf8(const char* str, size_t length)
{
    size_t i;
    int nBytes;
    unsigned char chr;

    i = 0;
    nBytes = 0;
    while (i < length) {
        chr = *(str + i);

        if (nBytes == 0) {
            if ((chr & 0x80) != 0) {
                while ((chr & 0x80) != 0) {
                    chr <<= 1;
                    nBytes++;
                }
                if ((nBytes < 2) || (nBytes > 6)) {
                    return 0;
                }
                nBytes--;
            }
        } else {
            if ((chr & 0xC0) != 0x80) {
                return 0;
            }
            nBytes--;
        }
        i++;
    }
    return (nBytes == 0) ? S_SUCCESS : S_ERROR;
}

size_t wchar_to_char_s(const wchar_t* in, size_t inlen, char* out, size_t outlen)
{
    //_tsetlocale(LC_ALL, _T(""));
#if (TARGET_OS == OS_WIN)
    return WideCharToMultiByte(CP_ACP, 0, in, inlen, out, outlen, NULL, false);
#elif (TARGET_OS == OS_POSIX)
    return wcstombs(out, in, outlen);
#elif (TARGET_OS == OS_MACH)
    return wcstombs(out, in, outlen);
#elif (TARGET_OS == OS_UNIX)
    return wcstombs(out, in, outlen);
#endif
}
size_t char_to_wchar_s(const char* in, size_t len, wchar_t* out, size_t outlen)
{
#if (TARGET_OS == OS_WIN)
    return MultiByteToWideChar(CP_ACP, 0, in, len, out, outlen);
#elif (TARGET_OS == OS_POSIX)
    return mbstowcs(out, in, outlen);
#elif (TARGET_OS == OS_MACH)
    return mbstowcs(out, in, outlen);
#elif (TARGET_OS == OS_UNIX)
    return mbstowcs(out, in, outlen);
#endif
}

char* wchar_to_char(const wchar_t* in, size_t len)
{
    char* ptr = NULL;
#if (TARGET_OS == OS_WIN)
    int size = 0;
    size = WideCharToMultiByte(CP_ACP, 0, in, -1, NULL, 0, NULL, false);
    ptr = (char*)calloc(size + 1, sizeof(char));
    rc_error(ptr != NULL, NULL);
    WideCharToMultiByte(CP_ACP, 0, in, len, ptr, size, NULL, false);
#elif (TARGET_OS == OS_POSIX)
    size_t size = wcstombs(NULL, in, 0);
    ptr = (char*)calloc(size + 1, sizeof(char));
    rc_error(ptr != NULL, NULL);
    wcstombs(ptr, in, size);
#elif (TARGET_OS == OS_MACH)
    size_t size = wcstombs(NULL, in, 0);
    ptr = (char*)calloc(size + 1, sizeof(char));
    rc_error(ptr != NULL, NULL);
    wcstombs(ptr, in, size);
#elif (TARGET_OS == OS_UNIX)
    size_t size = wcstombs(NULL, in, 0);
    ptr = (char*)calloc(size + 1, sizeof(char));
    rc_error(ptr != NULL, NULL);
    wcstombs(ptr, in, size);
#endif
    return ptr;
}

wchar_t* char_to_wchar(const char* in, size_t len)
{
    wchar_t* ptr = NULL;

#if (TARGET_OS == OS_WIN)
    int size = 0;
    size = MultiByteToWideChar(CP_ACP, 0, in, -1, NULL, 0);
    ptr = (wchar_t*)heap_calloc(size + 1, sizeof(wchar_t));
    rc_error(ptr != NULL, NULL);
    MultiByteToWideChar(CP_ACP, 0, in, -1, ptr, size);
#elif (TARGET_OS == OS_POSIX)
    size_t size = mbstowcs(NULL, in, 0);
    ptr = (wchar_t*)heap_calloc(size + 1, sizeof(wchar_t));
    rc_error(ptr != NULL, NULL);
    mbstowcs(ptr, in, size);
#elif (TARGET_OS == OS_MACH)
    size_t size = mbstowcs(NULL, in, 0);
    ptr = (wchar_t*)heap_calloc(size + 1, sizeof(wchar_t));
    rc_error(ptr != NULL, NULL);
    mbstowcs(ptr, in, size);
#endif

    return ptr;
}

char* wchartolocalechar(const wchar_t* in, size_t len, const char* locale)
{
    // setlocale(LC_ALL, "en_GB.UTF-8")
    return NULL;
}

wchar_t* chartolocalewchar(const char* in, size_t len, const char* locale)
{
    // setlocale(LC_ALL, "en_GB.UTF-8")
    return NULL;
}
